﻿using ezCloud.Api.Common;
using ezCloud.Api.Services;
using ezCloud.Data;
using Microsoft.AspNet.Identity;
using Nest;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlTypes;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using static ezCloud.Api.Common.STAAHReservationsUtility;

namespace ezCloud.Api.Controllers
{
    [ApiAuthorize]
    //[ApiAuthorize(Roles = "ROLE_HOTEL_OWNER")]
    [RoutePrefix("api/ChannelManager")]
    public class ChannelManagerController : ezController
    {
        public ChannelManagerController()
        {
        }

        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("AllChannelManagerData")]
        public async Task<IHttpActionResult> GetAllChannelMangerData()
        {
            var user = UserUtitily.getUserProfile();
            var CMConfiguration = context.CMConfigurations.Select(cm => new {
                cm.HotelId,
                cm.IsLastRoomAvailable,
                cm.LastModifiedDate,
                cm.LastModifiedUserId,
                cm.Source,
                cm.SourceId,
                cm.CMConfigurationId,
                cm.CMPassword,
                cm.CMPropertyId,
                cm.CMServiceUrl,
                cm.CMUser,
                IsAutoAssignRoom = cm.IsAutoAssignRoom == null ? false : cm.IsAutoAssignRoom
            }).FirstOrDefault(cm => cm.HotelId == user.HotelId);
            var SourceList = context.Source.Where(s => s.HotelId == user.HotelId).ToList();
            return Ok(new
            {
                CMConfiguration,
                SourceList
            });
        }


        public class postModel
        {
            public int hotel_id { get; set; }
        }
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("AllChannelManagerRoomTypeMapping")]
        public async Task<IHttpActionResult> GetAllChannelManagerRoomTypeMapping()
        {
            var user = UserUtitily.getUserProfile();
            //
            var hotelConfig = context.CMConfigurations.Where(config => config.HotelId == user.HotelId).FirstOrDefault();
            if (hotelConfig == null)
            {
                return Ok("CM_HOTEL_IS_NOT_REGISTER");
            }
            var RoomType_CMRoomTypeMapping = context.RoomTypes.Where(rt => rt.HotelId == user.HotelId && rt.IsDeleted == false)
                .GroupJoin(context.CMRoomTypeMappings.Where(cmrt => cmrt.HotelId == user.HotelId && cmrt.IsDeleted == false), rt => rt.RoomTypeId, cmrt => cmrt.RoomTypeId, (rt, cmrt) => new { rt, cmrt, rt.CMRoomRateMappingsList, rt.RoomPricesList }).ToList();
            var CMRoomTypes = new Object();
            var data = new postModel()
            {
                hotel_id = user.HotelId
            };
            foreach(var CMRoomType in RoomType_CMRoomTypeMapping)
            {
                if (CMRoomType.CMRoomRateMappingsList.Count() > 0)
                {
                    for(int i=0;i< CMRoomType.CMRoomRateMappingsList.Count; i++)
                    {
                        if (CMRoomType.CMRoomRateMappingsList[i].IsDeleted == true)
                        {
                            CMRoomType.CMRoomRateMappingsList.RemoveAt(i);
                            i--;
                        }
                    }
                }
            }
            HttpResponseMessage test = new HttpResponseMessage();
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(ConfigurationManager.AppSettings["ChannelManagerUrl"]);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
                HttpResponseMessage response = await client.PostAsJsonAsync("get_mapped_room", data);
                System.Diagnostics.Debug.WriteLine(response);
                if (response.IsSuccessStatusCode)
                {
                    test = response;
                    var jsonString = response.Content.ReadAsStringAsync();
                    jsonString.Wait();
                    
                        return Ok(new
                        {
                            CMRoomTypeMappings = RoomType_CMRoomTypeMapping,
                            CMRoomTypes = jsonString,
                        });
                }
                return BadRequest("AN_ERROR_OCCURRED_DURING_THE_MAPPING_PROCESS");
            }
            return BadRequest("AN_ERROR_OCCURRED_DURING_THE_MAPPING_PROCESS");
        }

        public class RegisterModel
        {
            public int hotel_id { set; get; }
            public string username { set; get; }
            public string password { set; get; }
            public string staah_hotel_id { set; get; }
            public string callback_url { set; get; }
            public string staah_service_url { set; get; }
            public bool is_last_room_available { set; get; }
            public int? source_id { set; get; }
        }
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("ChannelManagerRegister")]
        public async Task<IHttpActionResult> ChannelMangerRegister(RegisterModel register)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            if (context.CMConfigurations.Any(cm => cm.HotelId != register.hotel_id && cm.CMPropertyId == register.staah_hotel_id))
            {
                return BadRequest("ANOTHER_HOTEL_ALREADY_REGISTERED_WITH_CURRENT_STAAH_PROPERTY_ID");
            }

            #region Check Authentication
            var user = UserUtitily.getUserProfile();
            HttpResponseMessage test = new HttpResponseMessage();
            if (register !=null)
            {
                register.callback_url = ConfigurationManager.AppSettings["ChannelManagerCallpackUrl"];
            }

            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(ConfigurationManager.AppSettings["ChannelManagerUrl"]);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
                HttpResponseMessage response = await client.PostAsJsonAsync("registerandauthentication", register);
                System.Diagnostics.Debug.WriteLine(response);
                if (response.IsSuccessStatusCode)
                {
                    test = response;
                    var jsonString = response.Content.ReadAsStringAsync();
                    jsonString.Wait();
                    JObject Object_response = JObject.Parse(jsonString.Result);
                    if (Object_response["roomresponse"]["error"] != null)
                    {
                        return BadRequest("INFO_REGISTER_HOTEL_TO_CHANNEL_MANAGER_IS_NOT_CORRECT");
                    }
                }
                else
                {
                    return BadRequest("CAN_NOT_REGISTER_HOTEL_TO_CHANNEL_MANAGER");
                }
            }
            #endregion
            #region Register Staah
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(ConfigurationManager.AppSettings["ChannelManagerUrl"]);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
                HttpResponseMessage response = await client.PostAsJsonAsync("register", register);
                System.Diagnostics.Debug.WriteLine(response);
                if (response.IsSuccessStatusCode)
                {
                    #region Save CMConfigurations
                    var oldConfiguration = context.CMConfigurations.FirstOrDefault(cm => cm.HotelId == user.HotelId);
                    if (oldConfiguration != null)
                    {
                        oldConfiguration.CMUser = register.username;
                        oldConfiguration.CMPassword = register.password;
                        oldConfiguration.CMPropertyId = register.staah_hotel_id;
                        oldConfiguration.CMServiceUrl = register.staah_service_url;
                        //oldConfiguration.SourceId = register.source_id;
                        //oldConfiguration.IsLastRoomAvailable = register.is_last_room_available;
                        oldConfiguration.LastModifiedDate = DateTime.UtcNow;
                        oldConfiguration.LastModifiedUserId = user.UserId;
                    }
                    else
                    {
                        var newConfiguration = new CMConfigurations()
                        {
                            CMUser = register.username,
                            CMPassword = register.password,
                            CMPropertyId = register.staah_hotel_id,
                            CMServiceUrl = register.staah_service_url,
                            HotelId = user.HotelId,
                            IsLastRoomAvailable = true,
                            //SourceId = register.source_id,
                            CreatedDate = DateTime.UtcNow,
                            CreatedUserId = user.UserId,
                        };
                        context.CMConfigurations.InsertOnSubmit(newConfiguration);
                    }
                    context.SubmitChanges();
                    Elastic.IndexLastAudit(context);
                    return Ok();
                    #endregion
                }
                return BadRequest("CAN_NOT_REGISTER_HOTEL_TO_CHANNEL_MANAGER");
            }
            #endregion
        }
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("UpdateChannelManager")]
        public async Task<IHttpActionResult> UpdateChannelManager(CMConfigurations model)
        {
            var CMconfig = context.CMConfigurations.Where(m => m.CMConfigurationId == model.CMConfigurationId).FirstOrDefault();
            if (CMconfig != null)
            {
                CMconfig.IsLastRoomAvailable = model.IsLastRoomAvailable;
                CMconfig.SourceId = model.SourceId;
                CMconfig.IsAutoAssignRoom = model.IsAutoAssignRoom;
                context.SubmitChanges();
                return Ok();
            }
            return BadRequest("CMConfigurationId IS NOT CORRECT");
        }
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("ChannelManagerDeregister")]
        public async Task<IHttpActionResult> ChannelManagerDeregister(RegisterModel model)
        {
            #region Deregister Staah
            var user = UserUtitily.getUserProfile();
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(ConfigurationManager.AppSettings["ChannelManagerUrl"]);
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
                HttpResponseMessage response = await client.PostAsJsonAsync("deregister", model);
                System.Diagnostics.Debug.WriteLine(response);
                if (response.IsSuccessStatusCode)
                {
                    CMConfigurations oldCMConfig = context.CMConfigurations.Where(cm => cm.HotelId == user.HotelId).FirstOrDefault();
                    context.CMConfigurations.DeleteOnSubmit(oldCMConfig);
                    context.SubmitChanges();
                    return Ok();
                }
                return BadRequest("CAN_NOT_REGISTER_HOTEL_TO_CHANNEL_MANAGER");
            }
            #endregion
        }
        public class CMRoomTypeMappingModel
        {
            public int? CMRoomTypeMappingId { get; set; }
            public int RoomTypeId { get; set; }
            public int CMRoomTypeId { get; set; }
            public string CMRoomTypeName { get; set; }
            public bool IsSelected { get; set; }
        }

        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("AddCMRoomTypeMapping")]
        public async Task<IHttpActionResult> AddCMRoomTypeMapping(CMRoomTypeMappings model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            var user = UserUtitily.getUserProfile();
            var cmRoomTypeMappings = context.CMRoomTypeMappings.Where(cm => cm.HotelId == user.HotelId).ToList();
            //foreach (var roomTypeMapping in model)
            //{
            if (model.CMRoomTypeMappingId == 0)
            {
                //if (roomTypeMapping.IsSelected)
                //{
                var roomTypeMappingTemp = new CMRoomTypeMappings();
                roomTypeMappingTemp.HotelId = user.HotelId;
                roomTypeMappingTemp.CreatedDate = DateTime.UtcNow;
                roomTypeMappingTemp.CreatedUserId = user.UserId;
                roomTypeMappingTemp.IsAvailable = true;
                roomTypeMappingTemp.IsDeleted = false;
                roomTypeMappingTemp.RoomTypeId = model.RoomTypeId;
                roomTypeMappingTemp.CMRoomTypeId = model.CMRoomTypeId;
                roomTypeMappingTemp.CMRoomTypeName = model.CMRoomTypeName;
                context.CMRoomTypeMappings.InsertOnSubmit(roomTypeMappingTemp);
                //}
            }
            else
            {
                var currentCMRoomTypeMapping = cmRoomTypeMappings.FirstOrDefault(cm => cm.CMRoomTypeMappingId == model.CMRoomTypeMappingId);
                //if (!roomTypeMapping.IsSelected)
                //{
                //    context.CMRoomTypeMappings.DeleteOnSubmit(currentCMRoomTypeMapping);
                //}
                //else
                //{
                currentCMRoomTypeMapping.CMRoomTypeId = model.CMRoomTypeId;
                currentCMRoomTypeMapping.CMRoomTypeName = model.CMRoomTypeName;
                //}
            }
            //}
            context.SubmitChanges();
            Elastic.IndexLastAudit(context);
            return Ok();
        }

        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("AddCMRoomRateMapping")]
        public async Task<IHttpActionResult> AddCMRoomRateMapping(CMRoomRateMappings model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var user = UserUtitily.getUserProfile();

            if (model.CMRoomRateMappingId != 0)
            {
                var currentCMRoomRateMapping = context.CMRoomRateMappings.FirstOrDefault(rate => rate.HotelId == user.HotelId && rate.CMRoomRateMappingId == model.CMRoomRateMappingId);
                if (currentCMRoomRateMapping != null && currentCMRoomRateMapping.RoomPriceId == model.RoomPriceId && currentCMRoomRateMapping.RoomTypeId == model.RoomTypeId)
                {
                    currentCMRoomRateMapping.CMRoomRateId = model.CMRoomRateId;
                    currentCMRoomRateMapping.CMRoomRateName = model.CMRoomRateName;
                }
            }
            else
            {
                model.HotelId = user.HotelId;
                model.CreatedDate = DateTime.UtcNow;
                model.CreatedUserId = user.UserId;
                model.IsAvailable = true;
                model.IsDeleted = false;
                context.CMRoomRateMappings.InsertOnSubmit(model);
            }

            context.SubmitChanges();
            Elastic.IndexLastAudit(context);

            return Ok();
        }
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("RemoveCMRoomTypeMapping")]
        public async Task<IHttpActionResult> RemoveCMRoomTypeMapping(int CMRoomTypeMappingId)
        {
            if (CMRoomTypeMappingId == null)
            {
                return BadRequest("CMRoomTypeMappingId IS NULL");
            }
            var user = UserUtitily.getUserProfile();
            //delete CM Room Type
            var CMRoomType = context.CMRoomTypeMappings.Where(rt => rt.HotelId == user.HotelId && rt.CMRoomTypeMappingId == CMRoomTypeMappingId && rt.IsDeleted == false).FirstOrDefault();
            if (CMRoomType != null)
            {
                //delete CM Room Rate
                //var ListRoomRate = context.CMRoomRateMappings.Where(rr => rr.HotelId == user.HotelId && rr.RoomTypeId == CMRoomType.RoomTypeId).ToList();
                var ListRoomRate = CMRoomType.RoomTypes.CMRoomRateMappingsList;
                if (ListRoomRate.Count > 0)
                {
                    foreach (CMRoomRateMappings RoomRate in ListRoomRate)
                    {
                        RoomRate.IsDeleted = true;
                        RoomRate.DeletedDate = DateTime.UtcNow;
                        RoomRate.DeletedUserId = user.UserId;
                    }
                }
                CMRoomType.IsDeleted = true;
                CMRoomType.DeletedDate = DateTime.UtcNow;
                CMRoomType.DeletedUserId = user.UserId;
                context.SubmitChanges();
                Elastic.IndexLastAudit(context);
            }
            return Ok();
        }
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("RemoveCMRoomRateMapping")]
        public async Task<IHttpActionResult> RemoveCMRoomRateMapping(int CMRoomRateMappingId)
        {
            if (CMRoomRateMappingId == null)
            {
                return BadRequest("CMRoomTypeMappingId IS NULL");
            }
            var user = UserUtitily.getUserProfile();
            var RoomRate = context.CMRoomRateMappings.Where(m => m.CMRoomRateMappingId == CMRoomRateMappingId).FirstOrDefault();
            if (RoomRate != null)
            {
                RoomRate.IsDeleted = true;
                RoomRate.DeletedUserId = user.UserId;
                RoomRate.DeletedDate = DateTime.UtcNow;
            }
            context.SubmitChanges();
            Elastic.IndexLastAudit(context);
            return Ok();
        }
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("GetAvailabilityMatrixData")]
        public async Task<IHttpActionResult> GetAvailabilityMatrixData(DateTime from, DateTime to)
        {
            var user = UserUtitily.getUserProfile();
            var currentHotel = context.Hotels.FirstOrDefault(ht => ht.HotelId == user.HotelId);

            from = from.AddMinutes(-currentHotel.TimeZoneOffset);
            to = to.AddMinutes(-currentHotel.TimeZoneOffset);
            var cmRoomTypeMapping = context.RoomTypes.Where(rt => rt.HotelId == user.HotelId && rt.IsHidden == false).GroupJoin(context.CMRoomTypeMappings.Where(cmrt => cmrt.HotelId == user.HotelId && cmrt.IsDeleted == false), rt => rt.RoomTypeId, cmrt => cmrt.RoomTypeId, (rt, cmrt) => new { rt, cmrt }).ToList();
            var cmAvailabilityMatrix = context.CMAvailabilityMatrixs.Where(av => av.HotelId == user.HotelId && from <= av.MatrixDate && av.MatrixDate <= to).ToList();
            var RoomAvailabilityMatrix = Utilities.GetRoomAvailabilityMatrix(from, to);
            return Ok(new
            {
                cmRoomTypeMapping,
                cmAvailabilityMatrix,
                RoomAvailabilityMatrix,
                CMConfiguration = currentHotel.CMConfigurationsList.FirstOrDefault()
            });
        }

        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("UpdateAllowOverBooking")]
        public async Task<IHttpActionResult> UpdateAllowOverBooking(CMConfigurations model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            var user = UserUtitily.getUserProfile();
            var currentConfiguration = context.CMConfigurations.FirstOrDefault(conf => conf.HotelId == user.HotelId && conf.CMConfigurationId == model.CMConfigurationId);
            if (currentConfiguration != null)
            {
                currentConfiguration.IsAllowOverBooking = model.IsAllowOverBooking;
                currentConfiguration.LastModifiedDate = DateTime.UtcNow;
                currentConfiguration.LastModifiedUserId = user.UserId;
                context.SubmitChanges();
                Elastic.IndexLastAudit(context);
            }
            return Ok();

        }
        [HttpPost]
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("GetInventoryLogData")]
        public async Task<IHttpActionResult> GetInventoryLogData(InventoryLogModel model)
        {
            var user = Common.UserUtitily.getUserProfile();
            var currentHotel = context.Hotels.Where(ht => ht.HotelId == user.HotelId).FirstOrDefault();
            var timeZoneOffset = -currentHotel.TimeZoneOffset / 60;
            TimeSpan offSet = new TimeSpan(timeZoneOffset, 0, 0);
            if (model.CreateDateForm == null)
            {
                model.CreateDateForm = ((DateTime)SqlDateTime.MinValue).Date;
            }
            else
            {
                DateTimeOffset fromTemp = new DateTimeOffset(((DateTime)model.CreateDateForm).Year, ((DateTime)model.CreateDateForm).Month, ((DateTime)model.CreateDateForm).Day, ((DateTime)model.CreateDateForm).Hour, ((DateTime)model.CreateDateForm).Minute, ((DateTime)model.CreateDateForm).Second, offSet).ToOffset(TimeSpan.Zero);
                //model.ReservationFrom = fromTemp.Date;
                DateTime from = (DateTime)fromTemp.Date;
                from = from.AddMinutes(-currentHotel.TimeZoneOffset);
                model.CreateDateForm = from;
            }

            if (model.CreateDateTo == null)
            {
                model.CreateDateTo = ((DateTime)SqlDateTime.MaxValue).Date;
            }
            else
            {
                DateTimeOffset toTemp = new DateTimeOffset(((DateTime)model.CreateDateTo).Year, ((DateTime)model.CreateDateTo).Month, ((DateTime)model.CreateDateTo).Day, ((DateTime)model.CreateDateTo).Hour, ((DateTime)model.CreateDateTo).Minute, ((DateTime)model.CreateDateTo).Second, offSet).ToOffset(TimeSpan.Zero);
                DateTime to = (DateTime)toTemp.Date;
                to = to.AddDays(1);
                model.CreateDateTo = to;
            }
            //
            if (model.InventoryIncluded == true)
            {
                if (model.InventoryDateForm == null)
                {
                    model.InventoryDateForm = ((DateTime)SqlDateTime.MinValue).Date;
                }
                else
                {
                    DateTimeOffset fromTemp = new DateTimeOffset(((DateTime)model.InventoryDateForm).Year, ((DateTime)model.InventoryDateForm).Month, ((DateTime)model.InventoryDateForm).Day, ((DateTime)model.InventoryDateForm).Hour, ((DateTime)model.InventoryDateForm).Minute, ((DateTime)model.InventoryDateForm).Second, offSet).ToOffset(TimeSpan.Zero);
                    //model.ReservationFrom = fromTemp.Date;
                    DateTime from = (DateTime)fromTemp.Date;
                    from = from.AddMinutes(-currentHotel.TimeZoneOffset);
                    model.InventoryDateForm = from;
                }

                if (model.InventoryDateTo == null)
                {
                    model.InventoryDateTo = ((DateTime)SqlDateTime.MaxValue).Date;
                }
                else
                {
                    DateTimeOffset toTemp = new DateTimeOffset(((DateTime)model.InventoryDateTo).Year, ((DateTime)model.InventoryDateTo).Month, ((DateTime)model.InventoryDateTo).Day, ((DateTime)model.InventoryDateTo).Hour, ((DateTime)model.InventoryDateTo).Minute, ((DateTime)model.InventoryDateTo).Second, offSet).ToOffset(TimeSpan.Zero);
                    DateTime to = (DateTime)toTemp.Date;
                    to = to.AddDays(1);
                    to = to.AddMinutes(-currentHotel.TimeZoneOffset);
                    model.InventoryDateTo = to;
                }
            }
            else
            {
                model.InventoryDateForm = ((DateTime)SqlDateTime.MinValue).Date;
                model.InventoryDateTo = ((DateTime)SqlDateTime.MaxValue).Date;
            }
            var searchResults = context.CMBackgroundJobs.Join(context.AspNetUsers, bgj => bgj.CreatedUserId, anu => anu.Id,(bgj, anu) => new {
                bgj.CreatedDate,
                bgj.ActionName,
                bgj.ActionStatus,
                CanbeSold = bgj.ActionValue,
                bgj.EndDate,
                bgj.StartDate,
                bgj.HotelId,
                bgj.CMRoomTypeMappings,
                bgj.CMRoomTypeMappings.RoomTypes.RoomTypeName,
                anu.UserName,
                ActionUpdatedDate=bgj.ActionUpdatedDate==null? bgj.CreatedDate : bgj.ActionUpdatedDate,
            }).Where(bgj => bgj.HotelId == user.HotelId
                && bgj.CreatedDate >= model.CreateDateForm && bgj.CreatedDate <= model.CreateDateTo
                && bgj.StartDate < model.InventoryDateTo && bgj.EndDate >= model.InventoryDateForm
                ).OrderBy(o=>o.StartDate).ThenBy(t=>t.CreatedDate).ToList();
            if(searchResults.Count() > 0 && model.RoomTypeId > 0)
            {
                var tempResult = searchResults.Where(w => w.CMRoomTypeMappings.RoomTypeId == model.RoomTypeId).ToList();
                searchResults.Clear();
                searchResults = tempResult;
            }
            //var node = new Uri("http://localhost:9200");
            //var defaultIndex = ConfigurationSettings.AppSettings["elasticIndex"];
            //var settings = new ConnectionSettings(
            //                 node,
            //                 defaultIndex: defaultIndex
            //             );
            //var client = new ElasticClient(settings);
            //var filters = new List<FilterContainer>();
            //filters.Add(new FilterDescriptor<Common.ChannelManagerBackgroundJob.InventoryLog>().Term("inventory.hotel_id", user.HotelId));

            //var searchResults = client.Search<Common.ChannelManagerBackgroundJob.InventoryLog>(s => s
            //    .Index(defaultIndex)
            //    .Type("CMInventory")
            //    .Filter(f => f.And(filters.ToArray()))
            //    .SortDescending("date").From(0).Size(9999)
            //);
            return Ok(searchResults);
        }
        public class InventoryLogModel
        {
            private DateTime? createDateForm;
            private DateTime? createDateTo;
            private bool inventoryIncluded;
            private DateTime? inventoryDateForm;
            private DateTime? inventoryDateTo;
            private int roomTypeId;

            public DateTime? CreateDateForm
            {
                get
                {
                    return createDateForm;
                }

                set
                {
                    createDateForm = value;
                }
            }

            public DateTime? CreateDateTo
            {
                get
                {
                    return createDateTo;
                }

                set
                {
                    createDateTo = value;
                }
            }

            public bool InventoryIncluded
            {
                get
                {
                    return inventoryIncluded;
                }

                set
                {
                    inventoryIncluded = value;
                }
            }

            public DateTime? InventoryDateForm
            {
                get
                {
                    return inventoryDateForm;
                }

                set
                {
                    inventoryDateForm = value;
                }
            }

            public DateTime? InventoryDateTo
            {
                get
                {
                    return inventoryDateTo;
                }

                set
                {
                    inventoryDateTo = value;
                }
            }

            public int RoomTypeId
            {
                get
                {
                    return roomTypeId;
                }

                set
                {
                    roomTypeId = value;
                }
            }
        }

        public class CMAvailabilityMatrixModel
        {
            public CMAvailabilityMatrixs CMAvailabilityMatrixs { get; set; }
            public string ActionName { get; set; }
        }

        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("ProcessSaveAvailabilityMatrixData")]
        public async Task<IHttpActionResult> ProcessSaveAvailabilityMatrixData(CMAvailabilityMatrixModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            var user = UserUtitily.getUserProfile();
            switch (model.ActionName)
            {
                case "AVAILABILITY":
                    if (model.CMAvailabilityMatrixs != null && model.CMAvailabilityMatrixs.CMAvailabilityMatrixId != 0)
                    {
                        var currentCMAV = context.CMAvailabilityMatrixs.FirstOrDefault(av => av.HotelId == user.HotelId && av.CMAvailabilityMatrixId == model.CMAvailabilityMatrixs.CMAvailabilityMatrixId);
                        if (currentCMAV != null)
                        {
                            currentCMAV.CanBeSold = model.CMAvailabilityMatrixs.CanBeSold;
                            currentCMAV.Rate = model.CMAvailabilityMatrixs.Rate;
                            currentCMAV.MinLOS = model.CMAvailabilityMatrixs.MinLOS;
                            currentCMAV.MaxLOS = model.CMAvailabilityMatrixs.MaxLOS;
                            currentCMAV.Cta = model.CMAvailabilityMatrixs.Cta;
                            currentCMAV.Ctd = model.CMAvailabilityMatrixs.Ctd;
                            currentCMAV.StopSell = model.CMAvailabilityMatrixs.StopSell;
                            currentCMAV.LastModifiedDate = DateTime.UtcNow;
                            currentCMAV.LastModifiedUserId = user.UserId;
                        }
                    }
                    else
                    {
                        model.CMAvailabilityMatrixs.HotelId = user.HotelId;
                        model.CMAvailabilityMatrixs.CreatedDate = DateTime.UtcNow;
                        model.CMAvailabilityMatrixs.CreatedUserId = user.UserId;
                        context.CMAvailabilityMatrixs.InsertOnSubmit(model.CMAvailabilityMatrixs);
                    }

                    var newCMBackgroundJob = new CMBackgroundJobs
                    {
                        HotelId = user.HotelId,
                        CMRoomTypeMappingId = model.CMAvailabilityMatrixs.CMRoomTypeMappingId,
                        StartDate = model.CMAvailabilityMatrixs.MatrixDate,
                        EndDate = model.CMAvailabilityMatrixs.MatrixDate,
                        ActionStatus = 0,
                        ActionName = model.ActionName,
                        ActionValue = model.CMAvailabilityMatrixs.CanBeSold.ToString(),
                        CreatedDate = DateTime.UtcNow,
                        CreatedUserId = user.UserId
                    };
                    context.CMBackgroundJobs.InsertOnSubmit(newCMBackgroundJob);
                    break;
            }

            context.SubmitChanges();
            Elastic.IndexLastAudit(context);

            //send room available to CM
            //if (await Common.ChannelManagerBackgroundJob.ChannelManagerBackgroundJobScheduler())
            //{
                return Ok();
            //}
            //else
            //{
            //    return BadRequest("CAN_NOT_SEND_ROOM_AVAILABLE_TO_CM");
            //}

            
        }


        public class DateRangeModel
        {
            public DateTime from { get; set; }
            public DateTime to { get; set; }
        }
        public class BulkUpdateModel
        {
            public int updateType { get; set; }
            public string updateValue { get; set; }
            public List<DateRangeModel> dateRanges { get; set; }
            public List<int> roomTypes { get; set; }
        }

        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("ProcessSaveBulkUpdate")]
        public async Task<IHttpActionResult> ProcessSaveBulkUpdate(BulkUpdateModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            var user = UserUtitily.getUserProfile();
            var currentHotel = context.Hotels.Where(ht => ht.HotelId == user.HotelId).FirstOrDefault();
            switch (model.updateType)
            {
                case 1:
                    if (model.roomTypes != null && model.roomTypes.Count > 0)
                    {
                        foreach (var cmRoomTypeMappingId in model.roomTypes)
                        {
                            var CMRoomType = context.CMRoomTypeMappings.FirstOrDefault(cm => cm.HotelId == user.HotelId && cm.CMRoomTypeMappingId == cmRoomTypeMappingId);
                            if (CMRoomType != null)
                            {
                                if (model.dateRanges != null && model.dateRanges.Count > 0)
                                {
                                    foreach (var range in model.dateRanges)
                                    {
                                        if (range.from != null && range.to != null)
                                        {
                                            var newBackgroundJob = new CMBackgroundJobs
                                            {
                                                HotelId = user.HotelId,
                                                CMRoomTypeMappingId = cmRoomTypeMappingId,
                                                StartDate = range.from,
                                                EndDate = range.to,
                                                ActionName = "AVAILABILITY",
                                                ActionStatus = 0,
                                                ActionValue = model.updateValue,
                                                CreatedDate = DateTime.UtcNow,
                                                CreatedUserId = user.UserId,
                                            };
                                            context.CMBackgroundJobs.InsertOnSubmit(newBackgroundJob);
                                            var daterangeTemp = new Common.DateRange(range.from, range.to);
                                            var fixedRangeDayList = new List<DateTime>();
                                            var rangeTemp = daterangeTemp;
                                            foreach (DateTime rangeIndex in ReservationUtility.EachDayWithTime(rangeTemp, currentHotel))
                                            {
                                                fixedRangeDayList.Add(rangeIndex);
                                            }

                                            foreach (DateTime day in fixedRangeDayList)
                                            {
                                                var cmAvailabilityMatrix = context.CMAvailabilityMatrixs.FirstOrDefault(av => av.HotelId == user.HotelId && av.CMRoomTypeMappingId == cmRoomTypeMappingId && av.MatrixDate == day);
                                                if (cmAvailabilityMatrix != null)
                                                {
                                                    cmAvailabilityMatrix.CanBeSold = int.Parse(model.updateValue);
                                                    cmAvailabilityMatrix.LastModifiedDate = DateTime.UtcNow;
                                                    cmAvailabilityMatrix.LastModifiedUserId = user.UserId;
                                                }
                                                else
                                                {
                                                    var newCMAvailabilityMatrix = new CMAvailabilityMatrixs
                                                    {
                                                        HotelId = user.HotelId,
                                                        CMRoomTypeMappingId = cmRoomTypeMappingId,
                                                        MatrixDate = day,
                                                        CanBeSold = int.Parse(model.updateValue),
                                                        CreatedDate = DateTime.UtcNow,
                                                        CreatedUserId = user.UserId
                                                    };
                                                    context.CMAvailabilityMatrixs.InsertOnSubmit(newCMAvailabilityMatrix);
                                                }
                                            }

                                        }
                                    }
                                }
                            }
                        }
                        context.SubmitChanges();
                        Elastic.IndexLastAudit(context);
                    }
                    break;
            }

            //send room available to CM
            //if (await Common.ChannelManagerBackgroundJob.ChannelManagerBackgroundJobScheduler())
            //{
                return Ok();
            //}
            //else
            //{
            //    return BadRequest("CAN_NOT_SEND_ROOM_AVAILABLE_TO_CM");
            //}
        }

        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("TestSynchronization")]
        public async Task<IHttpActionResult> TestSynchronization()
        {
            Common.ChannelManagerBackgroundJob.ChannelManagerBackgroundJobScheduler();
            return Ok();
        }

        [Route("ReceiveReservationsFromSTAAH")]
        [AllowAnonymous]
        public async Task<IHttpActionResult> ProcessReceiveReservationsFromSTAAH(JObject STAAHData)
        {
            try
            {
                if (!InternalServices.isAllowed())
                {
                    return BadRequest("IP_NOT_ALLOW_EXIST");
                }

                STAAHReservations data = JsonConvert.DeserializeObject<STAAHReservations>(STAAHData.ToString());

                var context = new ezCloudDataContext();
                //var user = Common.UserUtitily.getUserProfile();
                var cmConfiguration = new CMConfigurations();
                var hotel_id = "";
                var HotelId = 0;
                foreach (var item in data.reservations.reservation)
                {
                    if (item.hotel_id.Trim().Length > 0)
                    {
                        hotel_id = item.hotel_id.Trim();
                        break;
                    }
                }

                var isHotelMapped = true;
                if (hotel_id.Length > 0)
                {
                    cmConfiguration = context.CMConfigurations.Where(c => c.CMPropertyId.ToLower().Trim() == hotel_id.ToLower()).FirstOrDefault();
                    if (cmConfiguration != null)
                        HotelId = (int)cmConfiguration.HotelId;
                    else
                    {
                        isHotelMapped = false;
                    }
                }
                else
                {
                    isHotelMapped = false;
                }

                if (!isHotelMapped)
                {
                    //send an email to administrator 
                    EmailService emailService = new EmailService();
                    IdentityMessage message = new IdentityMessage();
                    message.Destination = "hotro@ezcloud.vn";
                    message.Subject = "Error: Hotel id " + hotel_id + " is not mapped";
                    message.Body = "ezCloud Hotel - Hotel id " + hotel_id + " is not mapped, data received from STAAH: " + STAAHData.ToString();
                    string emailTemplate = File.ReadAllText(HttpContext.Current.Server.MapPath("/EmailTemplates/emailCMError.html"));
                    emailService.SendGmailAsync(message);
                    return BadRequest("HOTEL_DOES_NOT_EXIST");
                }

                var cmRoomTypeMappings = context.CMRoomTypeMappings.Where(cm => cm.HotelId == HotelId && cm.IsAvailable == true).ToList();
                var cmRoomRateMappings = context.CMRoomRateMappings.Where(cm => cm.HotelId == HotelId && cm.IsAvailable == true).ToList();
                var listCountry = context.Countries.ToList();
                var currentHotel = context.Hotels.Where(ht => ht.HotelId == HotelId).FirstOrDefault();
                var currencies = context.Money.Where(curr => curr.HotelId == HotelId).ToList();
                var currenciesISO = new List<Currencies>();
                foreach (var currency in currencies)
                {
                    var iso = context.Currencies.Where(curr => curr.CurrencyId == currency.CurrencyId).FirstOrDefault();
                    if (iso != null)
                    {
                        currenciesISO.Add(iso);
                    }
                }
                var defaultCurrency = currencies.FirstOrDefault(cur => cur.MoneyId == currentHotel.DefaultMoneyId);
                if (defaultCurrency == null)
                {
                    defaultCurrency = currencies.FirstOrDefault(cur => cur.MoneyName.ToLower() == "vnd");
                }

                foreach (var item in data.reservations.reservation)
                {
                    switch (item.booking_status.ToLower())
                    {
                        case "new":
                            string actionNew = "new";
                            STAAHReservationsUtility.AddNewSTAAHReservation(actionNew, data, item, context, currentHotel, currencies, cmRoomTypeMappings, cmRoomRateMappings, defaultCurrency, cmConfiguration, listCountry);
                            break;

                        case "cancel":
                            // Here we use the "real" cancel process in order to indexing reservation data
                            STAAHReservationsUtility.CancelSTAAHReservation(data, item, context, currentHotel);
                            break;

                        case "modify":
                            string actionModify = "modify";
                            var currentReservation = context.Reservations.FirstOrDefault(res => res.HotelId == HotelId && res.CMBookingId == item.booking_id && res.CMChannelRef == item.channel_ref);
                            if (currentReservation == null)
                            {
                                // send email

                                // Because there is no existent booking, just treat it as a new booking 
                                STAAHReservationsUtility.AddNewSTAAHReservation("new", data, item, context, currentHotel, currencies, cmRoomTypeMappings, cmRoomRateMappings, defaultCurrency, cmConfiguration, listCountry);
                            }
                            else
                            {

                                // Here we not gonna indexing cancel process due to modify is just a alternative of add new booking, so here just a normal cancel
                                var RRList = currentReservation.ReservationRoomsList;
                                foreach (var RR in currentReservation.ReservationRoomsList)
                                {
                                    RR.BookingStatus = "CANCELLED";
                                    RR.CancelDate = DateTime.UtcNow;
                                    RR.CancelUserId = currentHotel.HotelOwnerId;
                                    RR.CancelReason = "This reservation (RRID = " + RR.ReservationRoomId + ") was cancelled automatically in its modifing process";

                                    //If have deposit need to delete
                                    var listPayment = context.Payments.Where(p => p.HotelId == currentHotel.HotelId && p.ReservationRoomId == RR.ReservationRoomId && p.PaymentTypeName == "DEPOSIT").ToList();
                                    if (listPayment != null)
                                    {
                                        foreach (var payment in listPayment)
                                        {
                                            Payments oldPayment = payment;
                                            Payments deletedPayment = new Payments();
                                            deletedPayment.PaymentDescription = payment.PaymentDescription;
                                            deletedPayment.HotelId = payment.HotelId;
                                            deletedPayment.ReservationRoomId = payment.ReservationRoomId;
                                            deletedPayment.PaymentTypeName = "DELETED";
                                            deletedPayment.Amount = -payment.Amount;
                                            deletedPayment.CreatedDate = DateTime.UtcNow;
                                            deletedPayment.CreatedUserId = currentHotel.HotelOwnerId;
                                            deletedPayment.PaymentMethodId = payment.PaymentMethodId;
                                            deletedPayment.MoneyId = payment.MoneyId;
                                            deletedPayment.AmountInSpecificMoney = payment.AmountInSpecificMoney;
                                            deletedPayment.FolioId = payment.FolioId;
                                            deletedPayment.PaymentNumber = payment.PaymentNumber;
                                            deletedPayment.RefPaymentId = payment.PaymentId;

                                            context.Payments.InsertOnSubmit(deletedPayment);
                                            context.SubmitChanges();
                                            Common.Elastic.IndexLastAudit(context);
                                            oldPayment.RefPaymentId = deletedPayment.PaymentId;

                                        }
                                    }
                                }
                                context.SubmitChanges();

                                // And we add new booking with propriate action
                                STAAHReservationsUtility.AddNewSTAAHReservation(actionModify, data, item, context, currentHotel, currencies, cmRoomTypeMappings, cmRoomRateMappings, defaultCurrency, cmConfiguration, listCountry);

                                // update Available room on Matrix and send available room to CM
                                ReservationUtility.RebuildAvailableRoomOnMatrix("cancel", RRList.ToList(), currentHotel, context);
                            }
                            break;


                    }
                }
                //Elastic.IndexLastAudit(context);
               
            }
            catch (Exception ex)
            {

                string subject = "Error process CM:"+DateTime.UtcNow.AddHours(7);
                string body = "Message:"+ex.Message+",Source:"+ex.Source+ ";StackTrace:" + ex.StackTrace;

                EmailSender.SendEmail("dung.nguyen@ezcloud.vn", subject, body);
                string email = ConfigurationSettings.AppSettings["emailHotelReservationsFalse"];
                EmailSender.SendEmail(email, subject, body);
            }
            return Ok();
        }
        #region CMReservation
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("SearchCMReservationProcess")]
        public object SearchCMReservationProcess(SearchCMReservationProcessModel model)
        {
            var user = Common.UserUtitily.getUserProfile();
            var currentHotel = context.Hotels.Where(ht => ht.HotelId == user.HotelId).FirstOrDefault();
            var timeZoneOffset = -currentHotel.TimeZoneOffset / 60;
            TimeSpan offSet = new TimeSpan(timeZoneOffset, 0, 0);
            if (model.ReservationFrom == null)
            {
                model.ReservationFrom = ((DateTime)SqlDateTime.MinValue).Date;
            }
            else
            {
                DateTimeOffset fromTemp = new DateTimeOffset(((DateTime)model.ReservationFrom).Year, ((DateTime)model.ReservationFrom).Month, ((DateTime)model.ReservationFrom).Day, ((DateTime)model.ReservationFrom).Hour, ((DateTime)model.ReservationFrom).Minute, ((DateTime)model.ReservationFrom).Second, offSet).ToOffset(TimeSpan.Zero);
                //model.ReservationFrom = fromTemp.Date;
                DateTime from = (DateTime)fromTemp.Date;
                from = from.AddMinutes(-currentHotel.TimeZoneOffset);
                model.ReservationFrom = from;
            }

            if (model.ReservationTo == null)
            {
                model.ReservationTo = ((DateTime)SqlDateTime.MaxValue).Date;
            }
            else
            {
                DateTimeOffset toTemp = new DateTimeOffset(((DateTime)model.ReservationTo).Year, ((DateTime)model.ReservationTo).Month, ((DateTime)model.ReservationTo).Day, ((DateTime)model.ReservationTo).Hour, ((DateTime)model.ReservationTo).Minute, ((DateTime)model.ReservationTo).Second, offSet).ToOffset(TimeSpan.Zero);
                DateTime to = (DateTime)toTemp.Date.AddMinutes(-currentHotel.TimeZoneOffset);
                to = to.AddDays(1);
                model.ReservationTo = to;
            }

            //if (model.ReservationFrom != null)
            //{
            //    DateTimeOffset fromTemp = new DateTimeOffset(((DateTime)model.ReservationFrom).Year, ((DateTime)model.ReservationFrom).Month, ((DateTime)model.ReservationFrom).Day, ((DateTime)model.ReservationFrom).Hour, ((DateTime)model.ReservationFrom).Minute, ((DateTime)model.ReservationFrom).Second, offSet).ToOffset(TimeSpan.Zero);
            //    model.ReservationFrom = fromTemp.Date;
              
            //}
            //if (model.ReservationTo != null)
            //{
            //    DateTimeOffset toTemp = new DateTimeOffset(((DateTime)model.ReservationTo).Year, ((DateTime)model.ReservationTo).Month, ((DateTime)model.ReservationTo).Day, ((DateTime)model.ReservationTo).Hour, ((DateTime)model.ReservationTo).Minute, ((DateTime)model.ReservationTo).Second, offSet).ToOffset(TimeSpan.Zero);
            //    model.ReservationTo = toTemp.Date.AddDays(1);
              
            //}
            var reservationRooms = context.ReservationRooms.Where( rr => rr.HotelId == user.HotelId 
            && rr.CMConfirmed!=null 
            && rr.Reservations.CMChannelRef != null && rr.Reservations.CMBookingId!=null 
            && rr.CMReceiveBookingDate>=model.ReservationFrom && rr.CMReceiveBookingDate<model.ReservationTo  
            ).Select(rr => new {
                rr.ReservationRoomId,
                rr.Reservations,
                rr.ArrivalDate,
                rr.DepartureDate,
                rr.RoomTypes,
                rr.Rooms,
                rr.Note,
                rr.ReservationRoomNumber,
                rr.RoomPrices,
                rr.Price,
                rr.BookingStatus,
                rr.CMErrorDescription,
                rr.CMConfirmed,
                rr.Travellers,
                rr.CreatedDate,
                rr.CreatedUserId,
                rr.CheckInDate,
                rr.CheckInUserId,
                rr.CheckOutDate,
                rr.CheckOutUserId,
                rr.CancelDate,
                rr.CancelUserId,
                rr.CancelReason,
                rr.Reservations.Company,
                rr.Reservations.Source,
                rr.Reservations.Market,
                rr.CMReceiveBookingDate,
                rr.IsGroupMaster,
            }).ToList();
            //if (reservationRooms.Count > 0 && (model.ReservationFrom != null || model.ReservationTo != null))
            //{
            //    reservationRooms = reservationRooms.Where(rr => new DateTimeOffset(((DateTime)rr.Reservations.CreatedDate).Year, ((DateTime)rr.Reservations.CreatedDate).Month, ((DateTime)rr.Reservations.CreatedDate).Day, ((DateTime)rr.Reservations.CreatedDate).Hour, ((DateTime)rr.Reservations.CreatedDate).Minute, ((DateTime)rr.Reservations.CreatedDate).Second, offSet).ToOffset(TimeSpan.Zero).Date >= model.ReservationFrom && new DateTimeOffset(((DateTime)rr.Reservations.CreatedDate).Year, ((DateTime)rr.Reservations.CreatedDate).Month, ((DateTime)rr.Reservations.CreatedDate).Day, ((DateTime)rr.Reservations.CreatedDate).Hour, ((DateTime)rr.Reservations.CreatedDate).Minute, ((DateTime)rr.Reservations.CreatedDate).Second, offSet).ToOffset(TimeSpan.Zero).Date <= model.ReservationTo).ToList();
            //}
            if (reservationRooms.Count > 0 && model.CMBookingId != null && model.CMBookingId != "")
            {
                var reservationRoomTmp = reservationRooms.Where(rr => (rr.Reservations.CMBookingId == model.CMBookingId ||  rr.Reservations.CMChannelRef == model.CMBookingId)).ToList();
                reservationRooms.Clear();
                if (reservationRoomTmp != null)
                {
                    reservationRooms.AddRange(reservationRoomTmp);
                }
            }
            //if (reservationRooms.Count > 0 && model.CMConfirmed != null)
            //{
            //    var reservationRoomTmp = reservationRooms.Where(rr => rr.CMConfirmed == model.CMConfirmed).ToList();
            //    reservationRooms.Clear();
            //    if (reservationRoomTmp != null)
            //    {
            //        reservationRooms=reservationRoomTmp;
            //    }
            //}
            if (reservationRooms.Count > 0 && model.ArrivalIncluded == true)
            {
                if (model.ArrivalFrom == null)
                {
                    model.ArrivalFrom = (DateTime)SqlDateTime.MinValue;
                }
                else
                {
                    DateTimeOffset fromTemp = new DateTimeOffset(((DateTime)model.ArrivalFrom).Year, ((DateTime)model.ArrivalFrom).Month, ((DateTime)model.ArrivalFrom).Day, ((DateTime)model.ArrivalFrom).Hour, ((DateTime)model.ArrivalFrom).Minute, ((DateTime)model.ArrivalFrom).Second, offSet).ToOffset(TimeSpan.Zero);
                    DateTime from = fromTemp.Date;
                    from = from.AddMinutes(-currentHotel.TimeZoneOffset);
                    model.ArrivalFrom = from;
                }

                if (model.ArrivalTo == null)
                {
                    model.ArrivalTo = (DateTime)SqlDateTime.MaxValue;
                }
                else
                {
                    DateTimeOffset toTemp = new DateTimeOffset(((DateTime)model.ArrivalTo).Year, ((DateTime)model.ArrivalTo).Month, ((DateTime)model.ArrivalTo).Day, ((DateTime)model.ArrivalTo).Hour, ((DateTime)model.ArrivalTo).Minute, ((DateTime)model.ArrivalTo).Second, offSet).ToOffset(TimeSpan.Zero);
                    DateTime to = toTemp.Date;
                    to = to.AddDays(1);
                    model.ArrivalTo = to;
                }

                //if (model.ArrivalFrom != null)
                //{
                //    DateTimeOffset fromTemp = new DateTimeOffset(((DateTime)model.ArrivalFrom).Year, ((DateTime)model.ArrivalFrom).Month, ((DateTime)model.ArrivalFrom).Day, ((DateTime)model.ArrivalFrom).Hour, ((DateTime)model.ArrivalFrom).Minute, ((DateTime)model.ArrivalFrom).Second, offSet).ToOffset(TimeSpan.Zero);
                //    model.ArrivalFrom = fromTemp.Date;
                //}
                //if (model.ArrivalTo != null)
                //{
                //    DateTimeOffset toTemp = new DateTimeOffset(((DateTime)model.ArrivalTo).Year, ((DateTime)model.ArrivalTo).Month, ((DateTime)model.ArrivalTo).Day, ((DateTime)model.ArrivalTo).Hour, ((DateTime)model.ArrivalTo).Minute, ((DateTime)model.ArrivalTo).Second, offSet).ToOffset(TimeSpan.Zero);
                //    model.ArrivalTo = toTemp.Date;
                //}
                //reservationRooms = reservationRooms.Where(rr => new DateTimeOffset(((DateTime)rr.ArrivalDate).Year, ((DateTime)rr.ArrivalDate).Month, ((DateTime)rr.ArrivalDate).Day, ((DateTime)rr.ArrivalDate).Hour, ((DateTime)rr.ArrivalDate).Minute, ((DateTime)rr.ArrivalDate).Second, offSet).ToOffset(TimeSpan.Zero).Date >= model.ArrivalFrom && new DateTimeOffset(((DateTime)rr.ArrivalDate).Year, ((DateTime)rr.ArrivalDate).Month, ((DateTime)rr.ArrivalDate).Day, ((DateTime)rr.ArrivalDate).Hour, ((DateTime)rr.ArrivalDate).Minute, ((DateTime)rr.ArrivalDate).Second, offSet).ToOffset(TimeSpan.Zero).Date <= model.ArrivalTo).ToList();
                
                reservationRooms = reservationRooms.Where(rr => rr.ArrivalDate >= model.ArrivalFrom && rr.ArrivalDate < model.ArrivalTo).ToList();
                
            }

            if (reservationRooms.Count > 0 && model.BookedIncluded == true)
            {
                if (model.BookedFrom == null)
                {
                    model.BookedFrom = (DateTime)SqlDateTime.MinValue;
                }
                else
                {
                    DateTimeOffset fromTemp = new DateTimeOffset(((DateTime)model.BookedFrom).Year, ((DateTime)model.BookedFrom).Month, ((DateTime)model.BookedFrom).Day, ((DateTime)model.BookedFrom).Hour, ((DateTime)model.BookedFrom).Minute, ((DateTime)model.BookedFrom).Second, offSet).ToOffset(TimeSpan.Zero);
                    DateTime from = fromTemp.Date;
                    from = from.AddMinutes(-currentHotel.TimeZoneOffset);
                    model.BookedFrom = from;
                }

                if (model.BookedTo == null)
                {
                    model.BookedTo = (DateTime)SqlDateTime.MaxValue;
                }
                else
                {
                    DateTimeOffset toTemp = new DateTimeOffset(((DateTime)model.BookedTo).Year, ((DateTime)model.BookedTo).Month, ((DateTime)model.BookedTo).Day, ((DateTime)model.BookedTo).Hour, ((DateTime)model.BookedTo).Minute, ((DateTime)model.BookedTo).Second, offSet).ToOffset(TimeSpan.Zero);
                    DateTime to = toTemp.Date;
                    to = to.AddDays(1);
                    model.BookedTo = to;
                }

                //if (model.ArrivalFrom != null)
                //{
                //    DateTimeOffset fromTemp = new DateTimeOffset(((DateTime)model.ArrivalFrom).Year, ((DateTime)model.ArrivalFrom).Month, ((DateTime)model.ArrivalFrom).Day, ((DateTime)model.ArrivalFrom).Hour, ((DateTime)model.ArrivalFrom).Minute, ((DateTime)model.ArrivalFrom).Second, offSet).ToOffset(TimeSpan.Zero);
                //    model.ArrivalFrom = fromTemp.Date;
                //}
                //if (model.ArrivalTo != null)
                //{
                //    DateTimeOffset toTemp = new DateTimeOffset(((DateTime)model.ArrivalTo).Year, ((DateTime)model.ArrivalTo).Month, ((DateTime)model.ArrivalTo).Day, ((DateTime)model.ArrivalTo).Hour, ((DateTime)model.ArrivalTo).Minute, ((DateTime)model.ArrivalTo).Second, offSet).ToOffset(TimeSpan.Zero);
                //    model.ArrivalTo = toTemp.Date;
                //}
                //reservationRooms = reservationRooms.Where(rr => new DateTimeOffset(((DateTime)rr.ArrivalDate).Year, ((DateTime)rr.ArrivalDate).Month, ((DateTime)rr.ArrivalDate).Day, ((DateTime)rr.ArrivalDate).Hour, ((DateTime)rr.ArrivalDate).Minute, ((DateTime)rr.ArrivalDate).Second, offSet).ToOffset(TimeSpan.Zero).Date >= model.ArrivalFrom && new DateTimeOffset(((DateTime)rr.ArrivalDate).Year, ((DateTime)rr.ArrivalDate).Month, ((DateTime)rr.ArrivalDate).Day, ((DateTime)rr.ArrivalDate).Hour, ((DateTime)rr.ArrivalDate).Minute, ((DateTime)rr.ArrivalDate).Second, offSet).ToOffset(TimeSpan.Zero).Date <= model.ArrivalTo).ToList();
                //all booking from CM will set: CreatedDate is BookedDate, CMReceiveBookingDate is CreatedDate
                reservationRooms = reservationRooms.Where(rr => rr.CreatedDate >= model.BookedFrom && rr.CreatedDate < model.BookedTo).ToList();

            }
            var statusColors = context.StatusColors.Where(sc => sc.HotelId == user.HotelId).ToList();
            var alluser = context.Hotels.Where(ht => ht.HotelId == user.HotelId)
                            .Join(context.HotelOwners, ht => ht.HotelOwnerId, an => an.UserId, (ht, an) => new { Id = an.UserId, UserName = an.FullName })
                            .Union(context.Staffs.Where(st => st.HotelId == user.HotelId).Select(u => new { Id = u.UserId, UserName = u.StaffName })).ToList();
            var reservationInfo = new List<Models.ReservationInfo>();
            foreach (var reservation in reservationRooms)
            {
                //PaymentInfo infoTemp = new PaymentInfo();
                Models.ReservationInfo infoTemp = new Models.ReservationInfo();
                infoTemp.ReservationRoomId = reservation.ReservationRoomId;
                if (reservation.CreatedUserId != null)
                {
                    var CreatedUserName = alluser.Where(usr => usr.Id == reservation.CreatedUserId).FirstOrDefault();
                    if (CreatedUserName != null)
                    {
                        infoTemp.CreatedUserName = CreatedUserName.UserName;
                    }
                }

                if (reservation.CheckInUserId != null)
                {
                    var CheckInUserName = alluser.Where(usr => usr.Id == reservation.CheckInUserId).FirstOrDefault();
                    if (CheckInUserName != null)
                    {
                        infoTemp.CheckInUserName = CheckInUserName.UserName;
                    }
                }

                if (reservation.CheckOutUserId != null)
                {
                    var CheckOutUserName = alluser.Where(usr => usr.Id == reservation.CheckOutUserId).FirstOrDefault();
                    if (CheckOutUserName != null)
                    {
                        infoTemp.CheckOutUserName = CheckOutUserName.UserName;
                    }
                }
                if (reservation.CancelUserId != null)
                {
                    var CancelUserName = alluser.Where(usr => usr.Id == reservation.CancelUserId).FirstOrDefault();
                    if (CancelUserName != null)
                    {
                        infoTemp.CancelUserName = CancelUserName.UserName;
                    }
                }
                reservationInfo.Add(infoTemp);
            }
            return new {
                reservationRooms = reservationRooms,
                statusColors = statusColors,
                reservationInfo = reservationInfo
            };
        }
        public class SearchCMReservationProcessModel
        {
            public string CMBookingId { get; set; }
            public bool? CMConfirmed { get; set; }
            public bool ArrivalIncluded { get; set; }
            public DateTime? ArrivalFrom { get; set; }
            public DateTime? ArrivalTo { get; set; }
            public DateTime? ReservationFrom { get; set; }
            public DateTime? ReservationTo { get; set; }
            public bool BookedIncluded { get; set; }
            public DateTime? BookedFrom { get; set; }
            public DateTime? BookedTo { get; set; }
        }
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("GetReservationLogData")]
        public async Task<IHttpActionResult> GetReservationLogData(string CMBookingId)
        {
            var user = Common.UserUtitily.getUserProfile();
            var node = new Uri("http://localhost:9200");
            var defaultIndex = ConfigurationSettings.AppSettings["elasticIndex"];
            var settings = new ConnectionSettings(
                             node,
                             defaultIndex: defaultIndex
                         );
            var client = new ElasticClient(settings);
            var filters = new List<FilterContainer>();
            var searchResults = new SearchDescriptor<STAAHReservationLog>();
            filters.Add(new FilterDescriptor<STAAHReservationLog>().Term("data.reservations.reservation.booking_id", CMBookingId));
            searchResults.Filter(f => f.And(filters.ToArray()));
            searchResults.Index(defaultIndex);
            searchResults.Type("STAAHReservation");
            searchResults.SortDescending("date");

            var search = client.Search<STAAHReservationLog>(
                  searchResults
             );
            return Ok(search.Documents);
        }
        #endregion
        [HttpGet]
        [Route("HotelCMConfiguration")]
        [AllowAnonymous]
        public async Task<IHttpActionResult> HotelCMConfiguration()
        {
            var user = Common.UserUtitily.getUserProfile();
            var hotelConfig = context.CMConfigurations.Where(config => config.HotelId == user.HotelId).Select(s => new {
                s.CMConfigurationId,
                s.CMPassword,
                s.CMPropertyId,
                s.CMServiceUrl,
                s.CMUser,
                s.CreatedDate,
                s.HotelId,
                s.IsAllowOverBooking,
                s.IsLastRoomAvailable,
                s.SourceId,
                IsAutoAssignRoom = s.IsAutoAssignRoom == null ? false : s.IsAutoAssignRoom
            }).FirstOrDefault();
            var hotelCMModule = context.EzHotelModules.Where(ehm => ehm.HotelId == user.HotelId && ehm.EzModules.ModuleCode == "CMSTAAH" && ehm.Status == true).FirstOrDefault();
            return Ok(new
            {
                hotelConfig,
                hotelCMModule
            });
        }
        [HttpGet]
        [Route("GetRoomType")]
        public async Task<IHttpActionResult> getRoomType() {
            var user = Common.UserUtitily.getUserProfile();
            var roomType = context.RoomTypes.Where(rt => rt.HotelId == user.HotelId && rt.IsHidden == false && rt.IsDeleted == false).ToList();
            return Ok(roomType);
        }

        [HttpPost]
        [Route("EmailHotelReservationsFalse")]
        [AllowAnonymous]
        public async Task<IHttpActionResult> EmailHotelReservationsFalse(JObject STAAHData)
        {
            string subject = "Error process CM:" + DateTime.UtcNow.AddHours(7);
            string body = "New case error :" + STAAHData.ToString();
            string email = ConfigurationSettings.AppSettings["emailHotelReservationsFalse"];
            string ccerror = ConfigurationSettings.AppSettings["ccerror"];
            EmailSender.SendEmail(email, subject, body);
            EmailSender.SendEmail(ccerror, subject, body);

            return Ok();
        }


    }
}